// 声明一个游戏函数
function Game() {
  //红方选手
  this.redSquare = "O";
  // 黑方选手
  this.blackSquare = "X";
  //判断轮到谁下
  this.flag = true;
  // 每次落子的位置
  this.array = [];
  // 棋子的历史记录
  this.historys = [];
  // 悔棋的记录
  this.unhistorys = [];
  //选择撤销一步悔或撤销所有悔棋
  this.revocationType = false;
  //获取到.container元素
  this.container = document.querySelector(".container");
  //保存所有button元素
  let containerBtn = null;
}

//初始化游戏
Game.prototype.initGame = function () {
  this.createBoard();
  this.addEventListener();
  this.needBank();
  this.needRevokeBank();
}

//在游戏函数原型上增加方法，创建棋盘
Game.prototype.createBoard = function () {
  //创建一个容器
  let dom = document.createDocumentFragment();
  for (let i = 1; i <= 100; i++) {
    let btn = document.createElement("button");
    btn.className = i;
    dom.appendChild(btn);
  }
  // 将棋盘渲染
  this.container.appendChild(dom);
  //获到所有button元素
  this.containerBtn = document.querySelectorAll("button");
}

//为棋盘每个格子绑定点击事件
Game.prototype.addEventListener = function () {
  //调用事件委派
  this.delegate(this.container, 'click', 'button', (e) => {
    //如果此处已下棋子，则不执行方法
    if (e.target.innerText) return;
    this.flag ? this.isRedOrblack(e, this.redSquare) : this.isRedOrblack(e, this.blackSquare);
  });
}

//判断哪方下棋
Game.prototype.isRedOrblack = function (e, square) {
  // 保存当前事件的对象
  let nowDom = e.target;
  nowDom.innerText = square;
  // 记录在数组的对应类名序号的下标下
  this.array[nowDom.className] = square;
  this.historys.push(nowDom.className);
  //将悔棋记录清空
  this.unhistorys.length = 0;
  this.action(parseInt(nowDom.className), square);
  this.flag = !this.flag;
}

//判断胜负循环检索的方法
Game.prototype.decide = function (value, Operator, str, count) {
  for (i = 1; i < 5; i++) {
    if (this.array[value + Operator * i] === str)
      count++;
    else break;
  }
  return count;
}

//判断胜负
Game.prototype.action = function (value, str) {
  //垂直方向上的棋子
  let Hcount = 1;
  //水平方向上的棋子
  let Vcount = 1;
  //左对角方向上的棋子
  let LTacr = 1;
  //右方向上的棋子
  let RTacr = 1;
  //垂直方向
  Hcount = this.decide(value, -10, str, Hcount);
  Hcount = this.decide(value, 10, str, Hcount);
  // 水平方向
  Vcount = this.decide(value, -1, str, Vcount);
  Vcount = this.decide(value, 1, str, Vcount);
  //上左边对角方向
  LTacr = this.decide(value, -11, str, LTacr);
  LTacr = this.decide(value, 11, str, LTacr);
  //上右边对角方向
  RTacr = this.decide(value, -9, str, RTacr);
  RTacr = this.decide(value, 9, str, RTacr);
  (Hcount === 5 || Vcount === 5 || LTacr === 5 || RTacr === 5) && alert(str + "胜利");
}

// 悔棋
Game.prototype.needBank = function () {
  let BankDom = document.querySelector("#bank");
  //设置悔棋的相应数据
  let setBank = () => {
    //拿到记录中的棋子下标
    let number = parseInt(this.historys.pop());
    // 记录需要悔棋棋子的下标
    this.unhistorys.push(number);
    // 记录棋子值的数组中的下标对应按钮的类名的值
    this.array[number] = "";
    // 更改下棋的选手
    this.flag = !this.flag;
    // 返回棋子位置的数组在末尾拿掉对应的值减去一就是该btn按钮的下标
    return number - 1;
  }
  BankDom.onclick = () => {
    if (this.historys.length) {
      let number = setBank();
      // 对应的button按钮元素下标需要类名值减一
      this.containerBtn[number].innerText = "";
    }
  }
}

//撤销悔棋
Game.prototype.needRevokeBank = function () {
  let revokeBank = document.querySelector("#revokeBank");
  //将悔掉的棋重新赋值
  function setValue(number, square, isAction) {
    let target = this.containerBtn[number - 1];
    target.innerText = square;
    this.array[number] = square;
    isAction && this.action(parseInt(target.className), square);
    // 更改下棋的选手
    this.flag = !this.flag;
  }
  //绑定事件
  revokeBank.onclick = () => {
    if (!this.unhistorys.length) return;
    if (this.revocationType) {
      for (let i = this.unhistorys.length - 1; i >= 0; i--) {
        this.historys.push(this.unhistorys[i]);
        this.flag ? setValue.call(this, this.unhistorys[i], this.redSquare, false) : setValue.call(this, this.unhistorys[i], this.blackSquare, false)
      }
      //将悔棋记录清空
      this.unhistorys.length = 0;
    }
    else {
      let add = this.unhistorys.pop();
      this.historys.push(add);
      this.flag ? setValue.call(this, add, this.redSquare, true) : setValue.call(this, add, this.blackSquare, true);
    }
  }
}
//事件委派方法
Game.prototype.delegate = function (element, eventType, selector, fn) {
  element.addEventListener(eventType, e => {
    let el = e.target;
    while (!el.matches(selector)) {
      if (element === el) {
        el = null;
        break;
      }
      el = el.parentNode;
    }
    el && fn.call(el, e, el)
  });
  return element
};